#include "GY_ScaleToFitGroup.h"
#include "Graphics/GY_GraphicsReflection.h"
#include <QtMath>

GY_ScaleToFitGroup::GY_ScaleToFitGroup(const QString &guid, QGraphicsItem *parent)
    : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    setContainerEditPointF();
    this->setCenterPointF(m_PropertyInfoMap["position"].propertyValue.toPointF());
    m_pSimpleGroup = new GY_SimpleGroup(QString("%1_SimpleGroup").arg(guid),this);
    this->addToGroup(m_pSimpleGroup);
    m_ChildrensMap.insert(m_pSimpleGroup->getGuid(),m_pSimpleGroup);
    m_pSimpleGroup->setPos(QPointF(0,0));
}

GY_ScaleToFitGroup::~GY_ScaleToFitGroup()
{

}

bool GY_ScaleToFitGroup::addItem(GY_Object *pItem)
{
    //先拉伸再放入组件
    qreal scale = m_pSimpleGroup->scale();

    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        //不同情况不同处理方式
        if(pItem->getPropertyMap().contains("Position")) {
            //获取图形中心点位
            QPointF point;
            point = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Position"].propertyValue.toPointF());
            pItem->updateProperty("Position",(point*(1/scale)));
        }else if(pItem->getPropertyMap().contains("Center")) {
            //获取图形中心点位
            QPointF point;
            point = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Center"].propertyValue.toPointF());
            pItem->updateProperty("Center",(point*(1/scale)));
        }else if(pItem->getUserData(ClassType).toString() == "LinearTick") {
            //获取图形点位
            QPointF StartPoint;
            QPointF EndPoint;
            StartPoint = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["StartPoint"].propertyValue.toPointF());
            EndPoint = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["EndPoint"].propertyValue.toPointF());
            //两点差距不随比例缩放
            qreal w = abs(StartPoint.x()-EndPoint.x());
            qreal h = abs(StartPoint.y()-EndPoint.y());
            pItem->updateProperty("Point1",(StartPoint*(1/scale)));
            pItem->updateProperty("Point2",(StartPoint*(1/scale)+QPointF(w,h)));
        }else if((pItem->getUserData(ClassType).toString() == "Rect") || (pItem->getUserData(ClassType).toString() == "Line") ||
                 (pItem->getUserData(ClassType).toString() == "Fillet")) {
            //获取图形点位
            QPointF point1;
            QPointF point2;
            point1 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Point1"].propertyValue.toPointF());
            point2 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Point2"].propertyValue.toPointF());
            //两点差距不随比例缩放
            qreal w = abs(point1.x()-point2.x());
            qreal h = abs(point1.y()-point2.y());
            pItem->updateProperty("Point1",(point1*(1/scale)));
            pItem->updateProperty("Point2",(point1*(1/scale)+QPointF(w,h)));
        }else if((pItem->getUserData(ClassType).toString() == "PolygonItem") || (pItem->getUserData(ClassType).toString() == "PolylineItem")) {
            //获取图形点位
            QPointF point;
            point = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["PtsArray[0]"].propertyValue.toPointF());
            //所有点位按原大小移动
            for(int i=0;i<pItem->getPropertyMap()["PtsArray.Size"].propertyValue.toInt();i++) {
                QPointF point2;
                point2 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()[QString("PtsArray[%1]").arg(i)].propertyValue.toPointF());
                //两点差距不随比例缩放
                qreal w = abs(point.x()-point2.x());
                qreal h = abs(point.y()-point2.y());
                pItem->updateProperty(QString("PtsArray[%1]").arg(i),(point*(1/scale)+QPointF(w,h)));
            }
        }else if(pItem->getUserData(ClassType).toString() == "Bezier") {
            //获取图形点位
            QPointF point1;
            QPointF point2;
            QPointF Ctrl1;
            QPointF Ctrl2;
            point1 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Point1"].propertyValue.toPointF());
            point2 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Point2"].propertyValue.toPointF());
            Ctrl1 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Ctrl1"].propertyValue.toPointF());
            Ctrl2 = ((GY_BasicsGraphicsObject*)pItem)->mapToParent(pItem->getPropertyMap()["Ctrl2"].propertyValue.toPointF());
            //两点差距不随比例缩放
            qreal w = abs(point1.x()-point2.x());
            qreal h = abs(point1.y()-point2.y());
            qreal w1 = abs(point1.x()-Ctrl1.x());
            qreal h1 = abs(point1.y()-Ctrl1.y());
            qreal w2 = abs(point1.x()-Ctrl2.x());
            qreal h2 = abs(point1.y()-Ctrl2.y());
            pItem->updateProperty("Point1",(point1*(1/scale)));
            pItem->updateProperty("Point2",(point1*(1/scale)+QPointF(w,h)));
            pItem->updateProperty("Point2",(point1*(1/scale)+QPointF(w1,h1)));
            pItem->updateProperty("Point2",(point1*(1/scale)+QPointF(w2,h2)));
        }
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        //获取图形中心点位
        QPointF point;
        point = ((GY_ContainerTransform*)pItem)->mapToParent(pItem->getPropertyMap()["Position"].propertyValue.toPointF());
        //添加图形时位置比例和移动组缩放比例应该扩大一致
        pItem->updateProperty("Position",(point*(1/scale)));
    }
    //移动容器回到原比例
    m_pSimpleGroup->setScale(1);
    m_pSimpleGroup->addItem(pItem);
    connect(pItem,&GY_Object::itemRectChange,this,&GY_ScaleToFitGroup::updateDraw,Qt::QueuedConnection);
    updateDraw();
    return true;
}

bool GY_ScaleToFitGroup::addItemCopy(GY_Object *pItem)
{
    m_pSimpleGroup->addItem(pItem);
    connect(pItem,&GY_Object::itemRectChange,this,&GY_ScaleToFitGroup::updateDraw,Qt::QueuedConnection);
    return true;
}

bool GY_ScaleToFitGroup::removItem(const QString &guid)
{
    return m_pSimpleGroup->removItem(guid);
}

bool GY_ScaleToFitGroup::removItem(const GY_Object *pItem)
{
    //获取图形中心点位（在拉伸组时的位置）
    QPointF point;
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        //不同情况不同处理方式
        if(((GY_BasicsGraphicsObject*)pItem)->getPropertyMap().contains("Position")) {
            point = ((GY_BasicsGraphicsObject*)pItem)->mapToScene(((GY_BasicsGraphicsObject*)pItem)->getPropertyMap()["Position"].propertyValue.toPointF());
        }else if(((GY_BasicsGraphicsObject*)pItem)->getPropertyMap().contains("Center")) {
            point = ((GY_BasicsGraphicsObject*)pItem)->mapToScene(((GY_BasicsGraphicsObject*)pItem)->getPropertyMap()["Center"].propertyValue.toPointF());
        }
        //拉伸回原比例
        m_pSimpleGroup->setScale(1);
        //移出组件
        m_pSimpleGroup->removItem(pItem);
        this->GY_ContainerTransform::removItem(pItem);
        //变换位置移出组后，设置回原拉伸组时的位置
        ((GY_BasicsGraphicsObject*)pItem)->updateProperty("Center",point);
        ((GY_BasicsGraphicsObject*)pItem)->updateProperty("Position",point);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        point = ((GY_ContainerTransform*)pItem)->mapToScene(((GY_ContainerTransform*)pItem)->getPropertyMap()["Position"].propertyValue.toPointF());
        //拉伸回原比例
        m_pSimpleGroup->setScale(1);
        //移出组件
        m_pSimpleGroup->removItem(pItem);
        this->GY_ContainerTransform::removItem(pItem);
        //变换位置移出组后，设置回原拉伸组时的位置
        ((GY_BasicsGraphicsObject*)pItem)->updateProperty("Position",point);
    }
    updateDraw();
    //取消关联
    disconnect((GY_Object*)pItem,0,this,0);
    return true;
}

GY_Object *GY_ScaleToFitGroup::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pSimpleGroup->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
        ((GY_ScaleToFitGroup*)pObj)->addItemCopy(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

void GY_ScaleToFitGroup::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ScaleToFitGroup::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    GY_PropertyInfo point1PropertyInfo(this);
    point1PropertyInfo.propertyName="Point1";
    point1PropertyInfo.propertyValue=QPointF(-50,-50);
    point1PropertyInfo.updateType = MoveUpdate|Update|PointOfRelative;
    point1PropertyInfo.propertyType = PointPropertyType;
    point1PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ScaleToFitGroup::updatePoint1;
    m_PropertyInfoMap.insert("Point1",point1PropertyInfo);
    m_PropertyInfoMap[point1PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point2PropertyInfo(this);
    point2PropertyInfo.propertyName="Point2";
    point2PropertyInfo.propertyValue=QPointF(50,50);
    point2PropertyInfo.updateType = MoveUpdate|Update|PointOfRelative;
    point2PropertyInfo.propertyType = PointPropertyType;
    point2PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ScaleToFitGroup::updatePoint2;
    m_PropertyInfoMap.insert("Point2",point2PropertyInfo);
    m_PropertyInfoMap[point2PropertyInfo.propertyName].setConnect();
}

void GY_ScaleToFitGroup::updateDraw()
{
    QPointF point1 = m_PropertyInfoMap["Point1"].propertyValue.toPointF();
    QPointF point2 = m_PropertyInfoMap["Point2"].propertyValue.toPointF();

    QPointF leftPoint(((point1.x()<point2.x())?point1.x():point2.x()),((point1.y()<point2.y())?point1.y():point2.y()));
    //拉伸组长宽
    qreal width = abs(point2.x()-point1.x());
    qreal height = abs(point2.y()-point1.y());
    qreal propertionWidth;
    qreal propertionHeight;
    //移动组原来的边框大小，数据一直会是没拉伸前的值，拉伸改变图像值不变
    QRectF rect = m_pSimpleGroup->childrenBoundingRect();
    //横向比例和纵向比例
    propertionWidth = width/rect.width();
    propertionHeight = height/rect.height();
    //横向比例小，说明纵向有空间
    if(propertionWidth<=propertionHeight) {
        qreal h = (height-(rect.height()*propertionWidth))/2;
        m_pSimpleGroup->setPos(QPointF(leftPoint.x()-rect.x()*(propertionWidth),
                                       leftPoint.y()-rect.y()*(propertionWidth)+h));
        //先移动再拉伸
        m_pSimpleGroup->setScale(propertionWidth);
    }else {
        qreal w = (width-(rect.width()*propertionHeight))/2;
        m_pSimpleGroup->setPos(QPointF(leftPoint.x()-rect.x()*(propertionHeight)+w,
                                       leftPoint.y()-rect.y()*(propertionHeight)));
        //先移动再拉伸
        m_pSimpleGroup->setScale(propertionHeight);
    }
}

void GY_ScaleToFitGroup::setContainerEditPointF()
{
    QMap<QVariant,QPointF> editPoints = {
        {"Point1",m_PropertyInfoMap["Point1"].propertyValue.toPointF()},
        {"Point2",m_PropertyInfoMap["Point2"].propertyValue.toPointF()}
    };
    this->setEditPointF(editPoints);
}

bool GY_ScaleToFitGroup::updatePoint1(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    this->setEditPointF(name,this->mapFromScene(value.toPointF()));
    QPointF point = m_PropertyInfoMap["Point2"].propertyValue.toPointF()+this->mapFromScene(value.toPointF());
    this->setCenterPointF(point/2);
    updateDraw();
    return true;
}

bool GY_ScaleToFitGroup::updatePoint2(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    this->setEditPointF(name,this->mapFromScene(value.toPointF()));
    QPointF point = m_PropertyInfoMap["Point1"].propertyValue.toPointF()+this->mapFromScene(value.toPointF());
    this->setCenterPointF(point/2);
    updateDraw();
    return true;
}



